2023/12/234002字符

文件流

  • 流:数据的流动,从一个地方缓缓流到另一个地方。

  • 文件流:内存数据和磁盘数据之间的流动

    • 可读流:数据从源头流向内存
    • 可写流:数据从内存流向源头
    • 双工流:数据可从源头流向内存,也可从内存流向源头

可读流

const fs = require('fs');
const path = require('path');

const filename = path.resolve(__dirname, './pack.json');

const rs = fs.createReadStream(filename, {
    encoding: 'utf-8',  // 默认为 buffer
    highWaterMark: 1,  // 受 encoding 影响,encoding 为 null 时单位为字节,encoding 为 utf-8 时单位为字符
});

文件读取事件

  • open:文件打开
  • error:出现错误
  • data:每读到一部分数据出发一次
  • end:文件读取完毕
  • close:文件关闭
  • resume:文件读取暂停时触发
  • resume:文件恢复读取时触发
rs.on('open', () => {
    console.log('文件被打开');
});
rs.on('data', chunk => {
    console.log(chunk);  // 参数为每次读到的数据
    rs.pause();  // 暂停读取
});
rs.on('pause', () => {
    console.log('文件读取暂停');
    setTimeout(() => {
        rs.resume();  // 继续读取
    }, 1000);
});
rs.on('resume', () => {
    console.log('继续读取问价');
});

可写流

const fs = require('fs');
const path = require('path');

const filename = path.resolve(__dirname, './data/note.md');

const ws = fs.createWriteStream(filename, {
    encoding: 'utf-8',  // 默认为 buffer
    highWaterMark: 3,  // 不会受 encoding 影响,一次写入的字节数
});

文件写入事件

  • open:文件打开
  • error:出现错误
  • close:文件关闭
  • write:文件写入
  • end:写入文件结束触发(需手动触发)
  • drain:写入队列清空时触发
    const flag = ws.write('hello');
    console.log(flag);  //--> false
    

ws.write() 返回 true 表示下次调用可直接写入,为 false 表示写入内容 >= highWaterMark 规定的大小,超出部分暂时存在内存当中,产生背压

写一个可以持续写入数据并且不会产生背压的函数

const fs = require('fs');
const path = require('path');

/**
 * @param {string} filename 写入地址
 * @param {string} content 写入的重复内容
 * @param {number} content 要写入的文件大小
 */
function writeFile (filename, content, size = 1024 * 1024 * 5) {
    const ws = fs.createWriteStream(filename, {
        encoding: 'utf-8',  // 默认为 buffer
        highWaterMark: 16 * 1024,  // 不会受 encoding 影响,一次写入的字节数
    });
    
    let i = 0;
    function write () {
        let flag = true;
        while (i < size && flag) {
            flag = ws.write(content);
            i ++;
        }
    }
    write();
    
    ws.on('drain', () => {  // 写入队列清空时触发 drain 事件
        write();
    })
}

const filename = path.resolve(__dirname, './data/note.md');
writeFile(filename, 'Hello, word! ');

大型文件复制

const fs = require('fs');
const path = require('path');

async function copyFile () {
    const from = path.resolve(__dirname, './data/note.md');
    const to = path.resolve(__dirname, './data/note2.md');

    console.time();
    const rs = fs.createReadStream(from);
    const ws = fs.createWriteStream(to);

    rs.pipe(ws);  // 通道写入,== 下面的代码
    // rs.on('data', chunk => {
    //     // 读到一部分数据则暂停
    //     const flag = ws.write(chunk);
    //     if (!flag) {
    //         rs.pause();
    //     }
    // });
    // // 清空队列后继续读取文件
    // ws.on('drain', () => {
    //     rs.resume();
    // });

    rs.on('close', () => {
        ws.end();  // 手动结束写入操作
        console.timeEnd();
    })
}
copyFile();